﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class IMS_NavigatorLite : System.Web.UI.UserControl
{
    public string FolderName
    {
        set
        {
            FName = value;
        }
    }

    public string IsLTI
    {
        get
        {
            if (Request.QueryString["islti"] != null)
                return Request.QueryString["islti"];
            else
                return "";
        }
    }

    public string FolderTree = "";
    public string ServerCode = "";
    private string FName;
    public int node = 1;
    public bool TBO = false;

    private void CheckNonce()
    {
        string nonce = "";
        if (Request.QueryString["Nonce"] != null)
        {
            nonce = Request.QueryString["Nonce"];
            if (Session[nonce] != null)
            {
                System.Web.Security.FormsAuthentication.SetAuthCookie(Session[nonce].ToString(), false);
                Session.Remove(nonce);
            }
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsLTI != "")
            btnHome.Visible = false;
        CheckNonce();
        if (!Page.User.Identity.IsAuthenticated)
            Response.Redirect("~/default.aspx?Message=Authentication Failed - Please Login Again");
        if (!this.Visible)
            return;
        if (!CheckManifest())
        {
            lblError.Text = "There is no manifest file in this cartridge";
            return;
        }
        Folder fld = GetFolder();
        if (fld == null)
        {
            lblError.Text = "There are no folders in this cartridge";
            return;
        }
        FolderTree = BuildFolder(fld);
    }

    private bool CheckManifest()
    {
        System.IO.FileInfo fi = new System.IO.FileInfo(Server.MapPath("Courses/" + FName + "/imsmanifest.xml"));
        return fi.Exists;
    }

    protected void btnHome_Click(Object sender, EventArgs e)
    {
        Response.Redirect("~/default.aspx");
    }

    private string BuildFolder(Folder fld)
    {
        LMSData.Course crs = new LMSData.Course(FName);
        node = 1;
        string Tree = "<table><tr><td style='font-size: 14pt; text-decoration: underline; font-weight: bold;'>" + crs.CourseName + "</td></tr>";
        foreach (Folder fl in fld.Folders)
        {
            Tree += AddNode(fl, "subNodes0", 1, 8, true);
        }
        Tree += "</table>";
        ServerCode = ServerCode.Replace("\r", "").Replace("\n", "");
        return Tree;
    }

    private string AddNode(Folder fldr, string subNodeTitle, int tabs, int FontSize, bool Display)
    {
        string row = "";
        Resource rs = new Resource();
        if (fldr.Resources.Count > 0)
            rs = fldr.Resources[0];

        if (rs.Reference != null && !TBO)
        {
            if (rs.Reference.Contains("Report.aspx?Aid"))
            {
                row += "<hr>";
                TBO = true;
            }
        }
        row += "<tr id='node" + node.ToString() + "' title='" + subNodeTitle + "' style='display: block;'><td style='height: 20px; padding-left: " + Convert.ToString(tabs * 5) + "px;'>";

        if(fldr.Folders.Count > 0)
            row += "<a style='font-size: " + FontSize.ToString() + "pt; font-weight: bold; cursor: pointer; cursor: hand;' onclick='DisplayNodes(this, " + node.ToString() + ")' accesskey='closed'><img src='Images/plus.gif' /></a> ";

        if (rs.Type == "webcontent")
        {
            row += "<a id='nodeData" + node.ToString() + "' style='font-size: " + FontSize.ToString() + "pt; color: #000099; cursor: pointer; cursor: hand;' onclick='SelectNode(id, " + node.ToString() + ", 1)'>" + fldr.Title + "</a>";
            ServerCode += "|*|Courses/" + FName + "/" + rs.Reference;
        }
        else if (rs.Type == "associatedcontent/imscc_xmlv1p0/learning-application-resource")
        {
            row += "<a id='nodeData" + node.ToString() + "' style='font-size: " + FontSize.ToString() + "pt; color: #000099; cursor: pointer; cursor: hand;' onclick='SelectNode(id, " + node.ToString() + ", 1)'>" + fldr.Title + "</a>";
            ServerCode += "|*|Courses/" + FName + "/" + rs.Reference;
        }
        else if (rs.Type == "imswl_xmlv1p0")
        {
            row += "<a id='nodeData" + node.ToString() + "' style='font-size: " + FontSize.ToString() + "pt; color: #000099; cursor: pointer; cursor: hand;' onclick='SelectNode(id, " + node.ToString() + ", 1)'>" + fldr.Title + "</a>";
            ServerCode += "|*|" + rs.Reference;
        }
        else if (rs.Type == "imsdt_xmlv1p0")
        {
            row += "<a id='nodeData" + node.ToString() + "' style='font-size: " + FontSize.ToString() + "pt; color: #000099; cursor: pointer; cursor: hand;' onclick='SelectNode(id, " + node.ToString() + ", 4)'>" + fldr.Title + "</a>";
            ServerCode += "|*|" + rs.Title + "|Forum.aspx?ForumID=" + rs.Reference + "&CourseID=" + FName;
        }
        else if (rs.Type == "imsqti_xmlv1p2/imscc_xmlv1p0/assessment" || rs.Type == "imsqti_xmlv1p2/imscc_xmlv1p0/question-bank")
        {
            LMSData.Assessment asmt = new LMSData.Assessment(rs.Title);
            asmt.AssessmentName = fldr.Title;
            asmt.Save();
            row += "<a id='nodeData" + node.ToString() + "' style='font-size: " + FontSize.ToString() + "pt; color: #000099; cursor: pointer; cursor: hand;' onclick='SelectNode(id, " + node.ToString() + ", 2)'>" + fldr.Title + "</a>";
            ServerCode += "|*|Assessment.aspx?ALoc=Courses/" + FName + "/" + rs.Reference + "&Cid=" + FName + "&Aid=" + rs.Title;
        }
        else if (rs.Type == "imstiptdd_xmlv1p0")
        {
            row += "<a id='nodeData" + node.ToString() + "' style='font-size: " + FontSize.ToString() + "pt; color: #000099; cursor: pointer; cursor: hand;' onclick='SelectNode(id, " + node.ToString() + ", 3)'>" + fldr.Title + "</a>";
            ServerCode += "|*|LTILoader.aspx?LtiType=Simple&|" + rs.Title + "|" + rs.Reference + "|&CourseName=" + rs.Files[0] + "|&CourseID=" + rs.Files[1] + "&Key=12345|&Signature=Signature";
        }
        else if (rs.Type == "imsblti_v1p0" || rs.Type == "imsbasiclti_xmlv1p0")
        {
            row += "<a id='nodeData" + node.ToString() + "' style='font-size: " + FontSize.ToString() + "pt; color: #000099; cursor: pointer; cursor: hand;' onclick='SelectNode(id, " + node.ToString() + ", 3)'>" + fldr.Title + "</a>";
            ServerCode += "|*|LTILoader.aspx?LtiType=Basic&|" + rs.Title + "|" + rs.Reference + "|&Key=" + rs.Files[0] + "|&CourseName=" + Request.QueryString["FN"] + "|&CourseID=FILLER|&Signature=Signature";
        }
        else
        {
            row += "<a id='nodeData" + node.ToString() + "' style='font-size: " + FontSize.ToString() + "pt; color: #666600; cursor: pointer; cursor: hand;' onclick='SelectNode(id, " + node.ToString() + ", 5)'>" + fldr.Title + "</a>";
            ServerCode += "|*|" + rs.Reference;
        }

        row += "<table id='subNodes" + node.ToString() + "' title='" + subNodeTitle + "' style='display: none;'>";
        subNodeTitle = "subNodes" + node.ToString();

        node++;
        foreach (Folder fl in fldr.Folders)
            row += AddNode(fl, subNodeTitle, tabs + 1, 8, false);

        row += "</table></td></tr>";

        return row;
    }

    private Folder GetFolder()
    {
        XDocument xd = XDocument.Load(Server.MapPath("Courses/" + FName + "/imsmanifest.xml"));
        int AssessmentID = 1;
        LMSData.AssessmentController ac = new LMSData.AssessmentController();

        Folder MainFolder = new Folder();
        bool NoFolders = true;

        LMSData.Forum frm = null;
        LMSData.ForumCollection frmc = new LMSData.ForumCollection();

        foreach (XElement xe in xd.Descendants())
        {
            if (xe.Name.LocalName == "item")
            {
                MainFolder.Title = "Top Level";
                MainFolder.Identifier = xe.Attribute("identifier").Value;
                MainFolder.IdentifierRef = "null";
                MainFolder.Folders = new System.Collections.Generic.List<Folder>();
                MainFolder.Resources = new System.Collections.Generic.List<Resource>();
                foreach (XElement Child in GetAllChildSiblings(xe))
                {
                    if(Child.Name.LocalName == "item")
                        MainFolder.Folders.Add(AddFolder(Child));
                }
                NoFolders = false;
                break;
            }
        }

        if (NoFolders)
            return null;

        System.Collections.Generic.List<Resource> Resources = new System.Collections.Generic.List<Resource>();
        foreach (XElement xe in xd.Descendants())
        {
            Resource rs;
            if (xe.Name.LocalName == "resource")
            {
                rs = new Resource();
                rs.Files = new System.Collections.Generic.List<string>();
                rs.Identifier = xe.Attribute("identifier").Value;
                rs.Type = xe.Attribute("type").Value;
                if (xe.Attribute("href") != null && xe.Attribute("href").Value != "")
                    rs.Reference = xe.Attribute("href").Value;
                else if (xe.Descendants().Count() > 0)
                    if (xe.Descendants().First().Attribute("href") != null)
                        rs.Reference = xe.Descendants().First().Attribute("href").Value;
                
                if (rs.Type == "imswl_xmlv1p0" && xe.Descendants().Count() > 0)
                {
                    if (xe.Descendants().First().Attribute("href") != null)
                    {
                        xd = XDocument.Load(Server.MapPath("Courses/" + FName + "/" + xe.Descendants().First().Attribute("href").Value));
                        foreach (XElement wl in xd.Descendants())
                        {
                            if (wl.Name.LocalName == "title")
                                rs.Title = wl.Value;
                            if (wl.Name.LocalName == "url")
                                rs.Reference = wl.Attribute("href").Value;
                        }
                    }
                }
                if (rs.Type == "imsdt_xmlv1p0" && xe.Descendants().Count() > 0)
                {
                    frmc = new LMSData.ForumCollection();
                    frmc.LoadAndCloseReader(new SubSonic.Query(LMSData.Forum.Schema).WHERE(LMSData.Forum.Columns.CourseID, FName).WHERE(LMSData.Forum.Columns.IdentifierRef, rs.Identifier).ExecuteReader());
                    if (frmc.Count <= 0)
                        frm = new LMSData.Forum();
                    else
                        frm = frmc[0];

                    frm.CourseID = Int32.Parse(FName);
                    frm.IdentifierRef = rs.Identifier;

                    if (xe.Descendants().First().Attribute("href") != null)
                    {
                        xd = XDocument.Load(Server.MapPath("Courses/" + FName + "/" + xe.Descendants().First().Attribute("href").Value));
                        foreach (XElement dt in xd.Descendants())
                        {
                            if (dt.Name.LocalName == "title")
                            {
                                rs.Title = dt.Value;
                                frm.ForumName = dt.Value;
                            }
                            if (dt.Name.LocalName == "text")
                                frm.ForumText = dt.Value;
                            //if (dt.Name.LocalName == "text")
                            //    rs.Reference = PreProcessText(dt.Value);
                        }
                    }
                    frm.Save();
                    rs.Reference = frm.ForumID.ToString();
                }
                if (rs.Type == "imsqti_xmlv1p2/imscc_xmlv1p0/assessment" || rs.Type == "imsqti_xmlv1p2/imscc_xmlv1p0/question-bank" && xe.Descendants().Count() > 0)
                {
                    foreach (XElement qti in xe.Descendants())
                    {
                        if (qti.Attribute("href") != null)
                            rs.Reference = qti.Attribute("href").Value;
                    }
                    rs.Title = ac.CreateRecord(FName, AssessmentID, FName + AssessmentID.ToString() + " PHANtIm");
                        AssessmentID++;
                }
                if (rs.Type == "imstiptdd_xmlv1p0" && xe.Descendants().Count() > 0)
                {
                    if (xe.Descendants().First().Attribute("href") != null)
                    {
                        xd = XDocument.Load(Server.MapPath("Courses/" + FName + "/" + xe.Descendants().First().Attribute("href").Value));
                        rs.Files.Add("");
                        rs.Files.Add("");
                        rs.Files.Add("");
                        foreach (XElement ims in xd.Descendants())
                        {
                            if (ims.Name.LocalName == "tool_id")
                                rs.Title = ims.Value;
                            if (ims.Name.LocalName == "launchurl")
                                rs.Reference = ims.Value;
                            if (ims.Name.LocalName == "tool_title")
                                rs.Files[0] = ims.Value;
                            if (ims.Name.LocalName == "tool_name")
                                rs.Files[1] = ims.Value;
                            if (ims.Name.LocalName == "tool_signature")
                                rs.Files[2] = ims.Value;
                        }
                    }
                }
                if ((rs.Type == "imsblti_v1p0" || rs.Type == "imsbasiclti_xmlv1p0") && xe.Descendants().Count() > 0)
                {
                    if (xe.Descendants().First().Attribute("href") != null)
                    {
                        string imsFileName = Server.MapPath("Courses/" + FName + "/" + xe.Descendants().First().Attribute("href").Value);
                        xd = XDocument.Load(imsFileName);
                        rs.Reference = imsFileName.Replace(@"\", "/");
                        rs.Files.Add("");
                        //rs.Files.Add("");
                        //rs.Files.Add("");
                        //rs.Files.Add("");
                        foreach (XElement ims in xd.Descendants())
                        {
                            if (ims.Name.LocalName == "title")
                                rs.Title = ims.Value;
                            //if (ims.Name.LocalName == "launch_url")
                            //    rs.Reference = ims.Value;
                            //if (ims.Name.LocalName == "tool_title")
                            //    rs.Files[0] = ims.Value;
                            //if (ims.Name.LocalName == "tool_name")
                            //    rs.Files[1] = ims.Value;
                            //if (ims.Name.LocalName == "tool_signature")
                            //    rs.Files[2] = ims.Value;
                            if (ims.Name.LocalName == "custom" && ims.Descendants() != null)
                            {
                                foreach (XElement imsd in ims.Descendants())
                                {
                                    if (imsd.Name.LocalName == "parameter" && imsd.Attribute("key") != null)
                                        rs.Files[0] = imsd.Value;
                                }
                            }
                        }
                    }
                }
                foreach (XElement xz in xe.Descendants())
                {
                    if (xz.Attribute("href") != null)
                        rs.Files.Add(xz.Attribute("href").Value);
                }
                Resources.Add(rs);
            }
        }

        foreach (Resource rs in Resources)
            AddResouce(MainFolder, rs);

        LMSData.AssessmentController acon = new LMSData.AssessmentController();

        foreach (LMSData.Assessment asmt in acon.GetAssessments(FName))
        {
            Folder fi = new Folder();
            fi.Folders = new System.Collections.Generic.List<Folder>();
            fi.Resources = new System.Collections.Generic.List<Resource>();
            fi.Title = "Report for " + asmt.AssessmentName;
            Resource rs = new Resource();
            rs.Files = new System.Collections.Generic.List<string>();
            rs.Type = "imswl_xmlv1p0";
            rs.Reference = "Report.aspx?Aid=" + asmt.AssessmentID.ToString();
            fi.Resources.Add(rs);
            if (!fi.Title.Contains("PHANtIm") && !Roles.IsUserInRole(Membership.GetUser().UserName, "Student"))
                MainFolder.Folders.Add(fi);
        }

        return MainFolder;
    }

    private string PreProcessText(string Text)
    {
        string dq = char.ConvertFromUtf32(34);
        return Text.Replace("'", "`").Replace(dq, "##DQ##").Replace("$IMS-CC-FILEBASE$", GetSiteRoot() + "/Courses/" + FName + "/");
    }

    private Folder AddFolder(XElement node)
    {
        Folder Fldr = new Folder();
        Fldr.Title = node.Descendants().First().Value;
        Fldr.Identifier = node.Attribute("identifier").Value;
        Fldr.Folders = new System.Collections.Generic.List<Folder>();
        Fldr.Resources = new System.Collections.Generic.List<Resource>();
        
        if (node.Attribute("identifierref") == null)
        {
            foreach (XElement child in GetAllChildSiblings(node))
            {
                if(child.Name.LocalName == "item")
                    Fldr.Folders.Add(AddFolder(child));
            }
        }
        else if (node.Attribute("identifierref").Value == "")
        {
            foreach (XElement child in GetAllChildSiblings(node))
            {
                if (child.Name.LocalName == "item")
                    Fldr.Folders.Add(AddFolder(child));
            }
        }
        else
            Fldr.IdentifierRef = node.Attribute("identifierref").Value;

        return Fldr;
    }

    System.Collections.Generic.List<XElement> GetAllChildSiblings(XElement xe)
    {
        System.Collections.Generic.List<XElement> Children = new System.Collections.Generic.List<XElement>();
        Children.Add(xe.Descendants().First());
        Children.AddRange((xe.Descendants().First().ElementsAfterSelf().ToList()));
        return Children;
    }

    private void AddResouce(Folder Fldr, Resource rs)
    {
        if (Fldr.IdentifierRef == rs.Identifier)
            Fldr.Resources.Add(rs);
        foreach (Folder fl in Fldr.Folders)
            AddResouce(fl, rs);
    }

    public class Folder
    {
        public string Identifier;
        public string IdentifierRef;
        public string Title;
        public System.Collections.Generic.List<Folder> Folders;
        public System.Collections.Generic.List<Resource> Resources;
    }

    public class Resource
    {
        public string Title;
        public string Identifier;
        public string Type;
        public string Reference;
        public System.Collections.Generic.List<string> Files;
    }

    public static string GetSiteRoot()
    {
        string Port = System.Web.HttpContext.Current.Request.ServerVariables["SERVER_PORT"];
        if (Port == null || Port == "80" || Port == "443")
            Port = "";
        else
            Port = ":" + Port;

        string Protocol = System.Web.HttpContext.Current.Request.ServerVariables["SERVER_PORT_SECURE"];
        if (Protocol == null || Protocol == "0")
            Protocol = "http://";
        else
            Protocol = "https://";

        string appPath = System.Web.HttpContext.Current.Request.ApplicationPath;
        if (appPath == "/")
            appPath = "";

        string sOut = Protocol + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"] + Port + appPath;
        return sOut;
    }
}
